package com.atguigu.gmall.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderInfoService;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.atguigu.gmall.rabbit.constant.MqConst;
import com.atguigu.gmall.rabbit.service.RabbitService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class OrderInfoServiceImpl implements OrderInfoService {

    @Value("${ware.url}")
    private String wareUrl;
    @Autowired
    private ProductFeignClient productFeignClient;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RabbitService rabbitService;

    //提交订单
    @Override
    public Long submitOrder(OrderInfo orderInfo) {

        //1.保存订单表
        //将订单的商品清单，根据skuId重新加载一次
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        StringBuilder sb = new StringBuilder();
        orderDetailList.forEach(orderDetail -> {
            //防止页面的价格被人篡改
            BigDecimal price = productFeignClient.getPrice(orderDetail.getSkuId());
            orderDetail.setOrderPrice(price);
            //1.4订单描述
            sb.append(orderDetail.getSkuName() + " ");
        });
        //1.1总金额 为了安全，不能使用页面的值，应该在后台重新计算
        orderInfo.sumTotalAmount();
        //1.2订单状态
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        //1.3订单交易编号(第三方使用必须唯一）
        String outTradeNo = "ATGUIGU" +System.currentTimeMillis() + new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);
        //1.4订单描述
        if (sb != null && sb.length() > 100){
            orderInfo.setTradeBody(sb.toString().substring(0,100));
        } else {
            orderInfo.setTradeBody(sb.toString());
        }
        //1.5创建时间
        //Date curDate = new Date();
        Calendar calendar = Calendar.getInstance();
        //当前时间
        orderInfo.setCreateTime(calendar.getTime());
        //1.6失效时间
        calendar.add(Calendar.MINUTE,30);//当前时间加30分钟后
        // 未来时间（创建时间后30分钟的时间）
        orderInfo.setExpireTime(calendar.getTime());
        //1.7进度状态
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());
        //1.8图片路径
        //orderInfo.setImgUrl();
        orderInfoMapper.insert(orderInfo);//保存

        //2.保存订单详情表
        List<OrderDetail> orderDetailList1 = orderInfo.getOrderDetailList();
        List<String> skuIds = new ArrayList<>();
        orderDetailList1.forEach(orderDetail -> {
            //订单表的主键
            orderDetail.setOrderId(orderInfo.getId());
            skuIds.add(orderDetail.getSkuId().toString());
            orderDetailMapper.insert(orderDetail);
        });
        //3.1将已经生成订单的商品从购物车删除
    /*    String cacheH = RedisConst.USER_KEY_PREFIX + orderInfo.getUserId()
                + RedisConst.USER_CART_KEY_SUFFIX;
        redisTemplate.opsForHash().delete(cacheH,skuIds.toArray());*/
        //3.2删除数据库


        //4.取消订单

        //4.基于延迟插件的
   /*     rabbitService.sendDelayMessage(MqConst.EXCHANGE_DIRECT_ORDER_CANCEL,
                MqConst.ROUTING_ORDER_CANCEL,orderInfo.getId(),MqConst.DELAY_TIME);*/
        //基于死信


        return orderInfo.getId();
    }

    //校验库存
    @Override
    public boolean hasStock(Long skuId, Integer skuNum) {

        String url = wareUrl + "/hasStock?skuId="+skuId+"&num="+skuNum;
        return "1".equals(HttpClientUtil.doGet(url));
    }

    @Override
    public void cancelOrder(Long orderId) {
        //获取订单状态是否为未支付
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        if (null != orderInfo){
            //未支付
            if (orderInfo.getOrderStatus().equals(OrderStatus.UNPAID.name())){
                //是未支付更新订单状态为已关闭
                orderInfo.setOrderStatus(OrderStatus.CLOSED.name());
                //进度状态也需要更改为已关闭
                orderInfo.setProcessStatus(ProcessStatus.CLOSED.name());
                //更新订单
                orderInfoMapper.updateById(orderInfo);
                System.out.println("取消订单成功" + new Date());
            }
        }

    }

    //获取订单信息
    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        //订单详情
        orderInfo.setOrderDetailList(orderDetailMapper.selectList(new QueryWrapper<OrderDetail>()
                .eq("order_id",orderId)));
        return orderInfo;
    }

    //更新订单
    @Override
    public void updateOrderStatus(Long orderId,ProcessStatus processStatus) {
        //更新
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setId(orderId);
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        orderInfo.setProcessStatus(processStatus.name());
        orderInfoMapper.updateById(orderInfo);
    }

    //发送消息，通知仓库
    @Override
    public void sendOrderStatus(Long orderId) {
        //1.更新订单的状态为已通知仓库
        updateOrderStatus(orderId,ProcessStatus.NOTIFIED_WARE);
        //2.根据id查询订单数据
        OrderInfo orderInfo = getOrderInfo(orderId);
        //3.组织数据
        Map<String, Object> resultMap = initWareOrder(orderInfo);
        //4.通知仓库
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_WARE_STOCK,
                MqConst.ROUTING_WARE_STOCK, JSONObject.toJSONString(resultMap));
    }

    //组织发送给仓库的所需要的数据
    public Map<String,Object> initWareOrder(OrderInfo orderInfo){
        Map<String,Object> resultMap = new HashMap<>();

        resultMap.put("orderId",orderInfo.getId());
        resultMap.put("consignee",orderInfo.getConsignee());
        resultMap.put("consigneeTel",orderInfo.getConsigneeTel());
        resultMap.put("orderComment",orderInfo.getOrderComment());
        resultMap.put("orderBody",orderInfo.getTradeBody());
        resultMap.put("deliveryAddress",orderInfo.getDeliveryAddress());
        resultMap.put("paymentWay","ONLINE".equals(orderInfo.getPaymentWay())?"2":"1");

        //订单详情
        List<Map> details = orderInfo.getOrderDetailList().stream().map(orderDetail -> {
            Map map = new HashMap<>();
            map.put("skuId", orderDetail.getSkuId());
            map.put("skuName", orderDetail.getSkuName());
            map.put("skuNum", orderDetail.getSkuNum());
            return map;
        }).collect(Collectors.toList());
        resultMap.put("details",details);
        //传入仓库Id
        resultMap.put("wareId",orderInfo.getWareId());

        return resultMap;
    }

    //开始拆单
    @Override
    public List<OrderInfo> orderSplit(Long orderId, String wareSkuMap) {
        //一张订单可以拆分成多张订单 商品可能不在同一地点
        //以订单详情表进行拆单
        //*注意：订单表（原订单不删除，直接生成子订单，子订单依赖父订单）
        //      原订单的状态修改为已拆单
        //      子订单的状态为已支付（沿用原订单的状态）子订单的父订单id为父订单的id
        //*2：订单详情表 只将订单id改为子订单id

        //将参数二（wareSkuMap）转成List<Map>
        List<Map> mapList = JSONObject.parseArray(wareSkuMap, Map.class);

        //1.根据原订单的id查询原始订单信息
        OrderInfo orderInfoOrigin = getOrderInfo(orderId);

        List<OrderInfo> subOrderInfoList = mapList.stream().map(map -> {
            //遍历仓库
            //一个仓库是一个订单
            //子订单    来源于父订单
            OrderInfo subOrderInfo = new OrderInfo();
            BeanUtils.copyProperties(orderInfoOrigin,subOrderInfo);//把父订单所有属性拷贝给子订单
            //解决问题：1.设置子订单的id为null；
            subOrderInfo.setId(null);
            //2.设置父id
            subOrderInfo.setParentOrderId(orderInfoOrigin.getId());
            //保存子订单的订单详情
            List<String> skuIds = (List<String>) map.get("skuIds");

            //一个仓库有多个子订单详情集合
            List<OrderDetail> subOrderDetailList = new ArrayList<>();
            for (String skuId : skuIds) {
                //原始订单详情集合
                List<OrderDetail> orderDetailListOrigin = orderInfoOrigin.getOrderDetailList();
                for (OrderDetail orderDetailOrigin : orderDetailListOrigin) {
                    if (orderDetailOrigin.getSkuId().toString().equals(skuId)){
                        subOrderDetailList.add(orderDetailOrigin);
                        break;
                    }
                }
            }
            //3.设置新的订单集合,设置子订单的订单详情的引用
            subOrderInfo.setOrderDetailList(subOrderDetailList);
            //计算总金额
            subOrderInfo.sumTotalAmount();
            //保存子订单
            orderInfoMapper.insert(subOrderInfo);

            //更新当前子订单对应的多个订单详情（设置外键）
            subOrderInfo.getOrderDetailList().forEach(orderDetail -> {
                orderDetail.setOrderId(subOrderInfo.getId());
                orderDetailMapper.updateById(orderDetail);
            });
            return subOrderInfo;
        }).collect(Collectors.toList());

        //修改父订单的订单状态及进度状态
        updateOrderStatus(orderId,ProcessStatus.SPLIT);
        return subOrderInfoList;
    }

    //优化之后
    @Override
    public List<Map> orderSplit1(Long orderId, String wareSkuMap) {
        List<Map> mapList = JSONObject.parseArray(wareSkuMap, Map.class);

        //1.根据原订单的id查询原始订单信息
        OrderInfo orderInfoOrigin = getOrderInfo(orderId);
        //子订单集合
        List<Map> listMap = mapList.stream().map(map -> {
            //遍历仓库 每个仓库就是一个map
            //一个仓库是一个订单
            //子订单    来源于父订单
            OrderInfo subOrderInfo = new OrderInfo();
            BeanUtils.copyProperties(orderInfoOrigin,subOrderInfo);//把父订单所有属性拷贝给子订单
            //解决问题：1.设置子订单的id为null；
            subOrderInfo.setId(null);
            //2.设置父id
            subOrderInfo.setParentOrderId(orderInfoOrigin.getId());
            //3.记录当前子订单是哪个仓库
            subOrderInfo.setWareId(String.valueOf(map.get("wareId")));
            //保存子订单的订单详情
            List<String> skuIds = (List<String>) map.get("skuIds");

            //一个仓库有多个子订单详情集合
            List<OrderDetail> subOrderDetailList = new ArrayList<>();
            for (String skuId : skuIds) {
                //原始订单详情集合
                List<OrderDetail> orderDetailListOrigin = orderInfoOrigin.getOrderDetailList();
                for (OrderDetail orderDetailOrigin : orderDetailListOrigin) {
                    if (orderDetailOrigin.getSkuId().toString().equals(skuId)){
                        subOrderDetailList.add(orderDetailOrigin);
                        break;
                    }
                }
            }
            //3.设置新的订单集合,设置子订单的订单详情的引用
            subOrderInfo.setOrderDetailList(subOrderDetailList);
            //计算总金额
            subOrderInfo.sumTotalAmount();
            //保存子订单
            orderInfoMapper.insert(subOrderInfo);

            //更新当前子订单对应的多个订单详情（设置外键）
            subOrderInfo.getOrderDetailList().forEach(orderDetail -> {
                orderDetail.setOrderId(subOrderInfo.getId());
                orderDetailMapper.updateById(orderDetail);
            });
            return initWareOrder(subOrderInfo);
        }).collect(Collectors.toList());
        return mapList;

    }

}
